package org.custom.spring.boot.mybatis.utils;

import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.reflection.ReflectionException;
import org.apache.ibatis.reflection.SystemMetaObject;
import org.custom.spring.boot.mybatis.constant.MybatisConstant;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Mybatis-StatementHandler接口相关工具类
 *
 * @author 李坤
 */
public final class MybatisStatementHandlerUtil {
    private static final Logger logger = LoggerFactory.getLogger(MybatisStatementHandlerUtil.class);

    /**
     * 递归获取最底层的 MetaObject 对象
     *
     * @param metaObject 元数据
     *
     * @return 最底层元数据
     */
    public static MetaObject recursiveObtainMateObject(MetaObject metaObject) {
        try {
            Object value = metaObject.getValue(MybatisConstant.PLUGIN_TARGET);
            return recursiveObtainMateObject((StatementHandler) value);
        } catch (ReflectionException exception) {
            return metaObject;
        }
    }

    /**
     * 递归获取最底层的 MetaObject 对象
     *
     * @param handler 声名处理器
     *
     * @return 元数据对象
     */
    public static MetaObject recursiveObtainMateObject(StatementHandler handler) {
        MetaObject metaObject = SystemMetaObject.forObject(handler);

        try {
            StatementHandler target = (StatementHandler) metaObject.getValue(MybatisConstant.PLUGIN_TARGET);
            return MybatisStatementHandlerUtil.recursiveObtainMateObject(target);
        } catch (ReflectionException exception) {
            return metaObject;
        }
    }

    /**
     * 获取给定声明处理器中的映射数据
     *
     * @param handler 声明处理器
     *
     * @return 映射数据
     */
    public static MappedStatement getMappedStatement(StatementHandler handler) {
        // 递归获取最底层的 MetaObject-元数据 对象
        MetaObject metaObject = MybatisStatementHandlerUtil.recursiveObtainMateObject(handler);
        return (MappedStatement) metaObject.getValue(MybatisConstant.STATEMENT);
    }

    /**
     * 获取给定元数据中的映射数据
     *
     * @param metaObject 元数据
     *
     * @return 映射数据
     */
    public static MappedStatement getMappedStatement(MetaObject metaObject) {
        // 递归获取最底层的 MetaObject-元数据 对象
        metaObject = MybatisStatementHandlerUtil.recursiveObtainMateObject(metaObject);
        return (MappedStatement) metaObject.getValue(MybatisConstant.STATEMENT);
    }

    /**
     * 获取 绑定SQL 的 label标签-方法的全类型限定名
     *
     * @param handler 声明处理器
     *
     * @return 全类型限定名
     */
    public static String getBoundSqlLabel(StatementHandler handler) {
        // 递归获取最底层的 MetaObject-元数据 对象
        MetaObject metaObject = MybatisStatementHandlerUtil.recursiveObtainMateObject(handler);
        return MybatisStatementHandlerUtil.getMappedStatement(metaObject).getId();
    }

    /**
     * 获取 绑定SQL 的 label标签-方法的全类型限定名
     *
     * @param metaObject 元数据对象
     *
     * @return 全类型限定名
     */
    public static String getBoundSqlLabel(MetaObject metaObject) {
        // 递归获取最底层的 MetaObject-元数据 对象
        metaObject = MybatisStatementHandlerUtil.recursiveObtainMateObject(metaObject);
        return MybatisStatementHandlerUtil.getMappedStatement(metaObject).getId();
    }
}
